import { CanActivate, ExecutionContext, HttpException, HttpStatus, Injectable } from '@nestjs/common';
import { Observable } from 'rxjs';


import { JwtService } from '@nestjs/jwt'
import { jwtConstants } from './constants';
import { Request } from 'express';
import { Reflector } from '@nestjs/core';
import { IS_PUBLIC_KEY } from 'src/is-public/is-public.decorator';
@Injectable()
export class AuthGuard implements CanActivate {
  constructor(private readonly jwtService: JwtService,private reflector: Reflector ) { }
  async canActivate(
    context: ExecutionContext,
  ): Promise<boolean> {
    // console.log('token守卫')
    //总结一下，这段代码的作用是检查当前请求的处理程序或控制器是否被标记为公开的（即不需要权限验证）。
    // 如果找到了 IS_PUBLIC_KEY 元数据，并且其值为 true，那么 isPublic 变量将被设置为 true，否则为 false。
    // 这在实现权限控制时非常有用，可以根据 isPublic 的值来决定是否允许请求继续执行。
    // const isPublic = this.reflector.getAllAndOverride<boolean>(IS_PUBLIC_KEY, [
    //   context.getHandler(),
    //   context.getClass(),
    // ]);

    const isPublic = this.reflector.getAllAndOverride<boolean>(IS_PUBLIC_KEY, [
      context.getHandler(),
      context.getClass(),
    ]);
    console.log('isPublic',isPublic)
    if (isPublic) {
      console.log('该路径不需要token验证')
      return true;
    }

    const request = context.switchToHttp().getRequest<Request>()
    const token = this.extractTokenFromHeader(request)
   
    if (!token) {
      throw new HttpException('没有token信息', HttpStatus.NON_AUTHORITATIVE_INFORMATION)
    }

    try {
      const payload = await this.jwtService.verifyAsync(
        token,
        {
          secret: jwtConstants.secret
        }
      );
      //将token的信息设置到session中  类型与图形验证码  code的原理
      request.session['userId'] = payload.userId
    } catch (err) {
      throw new HttpException('token无效', HttpStatus.NON_AUTHORITATIVE_INFORMATION)
    }
    return true;
  }


  private extractTokenFromHeader(request: Request): string | undefined {
    const [type, token] = request.headers.authorization?.split(' ') ?? [];
    return type === 'Bearer' ? token : undefined;
  }
}
